package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.config.RedissonConfig;
import com.atguigu.gmall.product.service.TestService;
import com.baomidou.mybatisplus.generator.config.IFileCreate;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author Sanmier
 * @create 2020-12-07 11:12
 */
@Service
public class TestServiceImpl implements TestService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

//    @Override
//    public void testLock() {
//        //执行setnx
//        //Boolean flag = redisTemplate.opsForValue().setIfAbsent("lock", "ok");
//        //执行set 命令  包含 setnx,setex
//        //设置UUID  防止误删锁！
//        String uuid = UUID.randomUUID().toString();
//        Boolean flag = redisTemplate.opsForValue().setIfAbsent("lock", uuid,3, TimeUnit.SECONDS);
//        //flag = true上锁成功
//        if (flag) {
//            //获取数据
//            String values =redisTemplate.opsForValue().get("num");
//            //没有该值 return
//            if (StringUtils.isEmpty(values)){
//                return;
//            }
//            //有值就转换成int
//            int num = Integer.parseInt(values);
//            //reids中的num值+1
//            redisTemplate.opsForValue().set("num", String.valueOf(++num));
//            //执行完成之后
//           // String reidsuuid = redisTemplate.opsForValue().get("lock");
////            if (uuid.equals(reidsuuid)){
////                //如果匹配成功  则删除🔒
////                //判断完成之后  准备执行删除  但是此时CPU抢占了资源给了index 2 给redis的Lock 赋值v2
////                //此时cpu  又将执行权限给了index1
////                redisTemplate.delete("lock");
////            }
////            redisTemplate.delete("lock");
//
//            //使用Lua脚本删除
//            //定义Lua脚本
//            String script="if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
//
//            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
//            //赋值Lua脚本
//            redisScript.setScriptText(script);
//            redisScript.setResultType(Long.class);
//            //删除
//            redisTemplate.execute(redisScript, Arrays.asList("lock"),uuid);
//        }else {
//            //获取锁失败  等待
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            //自旋
//            testLock();
//        }
//    }



//    @Override
//    public synchronized void testLock() {
//         /*
//        获取缓存存储的数据	String  set num 0;
//            true:
//                ++num 再放入缓存
//            false:
//                return;
//         */
//        //  String 数据类型 放入数据的方法。redisTemplate.opsForValue() 了解：Jedis  jedis.set(key,value);
//        String values =redisTemplate.opsForValue().get("num");
//       //没有该值 return
//        if (StringUtils.isEmpty(values)){
//            return;
//        }
//        //有值就转换成int
//        int num = Integer.parseInt(values);
//        //reids中的num值+1
//        redisTemplate.opsForValue().set("num", String.valueOf(++num));
//    }
    @Override
    public void testLock() {
        //上锁
        RLock lock = null;
        try {
            lock = redissonClient.getLock("lock");
            lock.lock();
            //  String 数据类型 放入数据的方法。redisTemplate.opsForValue() 了解：Jedis  jedis.set(key,value);
            String values =redisTemplate.opsForValue().get("num");
            //没有该值 return
            if (StringUtils.isEmpty(values)){
                return;
            }
            //有值就转换成int
            int num = Integer.parseInt(values);
            //reids中的num值+1
            redisTemplate.opsForValue().set("num", String.valueOf(++num));
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }finally {
            if (lock!=null){
                lock.unlock();
            }
        }
    }

    @Override
    public String readLock() {
        //读写锁的时候 RReadWriteLock 对象使用的是同一把锁
        RReadWriteLock anyRWLock = redissonClient.getReadWriteLock("anyRWLock");
        //上🔒
        RLock rLock = anyRWLock.readLock();
        rLock.lock(10, TimeUnit.SECONDS);
        String msg = redisTemplate.opsForValue().get("msg");
        return msg;
    }

    @Override
    public String writeLock() {
        //获取🔒得对象
        RReadWriteLock anyRWLock = redissonClient.getReadWriteLock("anyRWLock");
        //上🔒
        RLock rlock = anyRWLock.writeLock();
        //10秒自动解锁
        rlock.lock(10, TimeUnit.SECONDS);
        //业务逻辑
        String uuid = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set("msg",uuid);
        return uuid;
    }
}
